From b30aadd3f032274c3a46350f1f55f20c7b11a756 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Sat, 26 Mar 2005 01:12:37 +0000 Subject: [PATCH] bitkeeper revision 1.1159.275.1 (4244b7056FS2uC4AapFJtHCNgoKPFg) No direct entry to __enter_scheduler allowed. Must always pass through softirq handler. Also domain_crash() now returns and defers descheduling from local CPU: old behaviour is still provided by domain_crash_synchronous(). Signed-off-by: Keir Fraser Signed-off-by: Christian Limpach --- xen/arch/x86/domain.c | 3 ++- xen/arch/x86/memory.c | 44 +++++++------------------------------ xen/arch/x86/shadow.c | 16 +++++++++----- xen/arch/x86/traps.c | 4 ++-- xen/arch/x86/x86_32/entry.S | 10 ++++----- xen/common/domain.c | 26 ++++++++++++---------- xen/common/schedule.c | 5 +++-- xen/include/xen/sched.h | 15 ++++++++++--- 8 files changed, 57 insertions(+), 66 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 812d14c506..d47910233a 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -82,7 +82,8 @@ void startup_cpu_idle_loop(void) /* Just some sanity to ensure that the scheduler is set up okay. */ ASSERT(current->id == IDLE_DOMAIN_ID); domain_unpause_by_systemcontroller(current); - __enter_scheduler(); + raise_softirq(SCHEDULE_SOFTIRQ); + do_softirq(); /* * Declares CPU setup done to the boot processor. diff --git a/xen/arch/x86/memory.c b/xen/arch/x86/memory.c index 6fb64a31fa..4c91d7374b 100644 --- a/xen/arch/x86/memory.c +++ b/xen/arch/x86/memory.c @@ -1686,7 +1686,7 @@ void ptwr_flush(const int which) MEM_LOG("ptwr: Could not read pte at %p\n", ptep); /* * Really a bug. We could read this PTE during the initial fault, - * and pagetables can't have changed meantime. XXX Multi-CPU guests? + * and pagetables can't have changed meantime. */ BUG(); } @@ -1713,7 +1713,7 @@ void ptwr_flush(const int which) MEM_LOG("ptwr: Could not update pte at %p\n", ptep); /* * Really a bug. We could write this PTE during the initial fault, - * and pagetables can't have changed meantime. XXX Multi-CPU guests? + * and pagetables can't have changed meantime. */ BUG(); } @@ -1771,6 +1771,7 @@ void ptwr_flush(const int which) *pl2e = mk_l2_pgentry(l2_pgentry_val(*pl2e) | _PAGE_PRESENT); } domain_crash(); + return; } if ( unlikely(sl1e != NULL) ) @@ -1834,13 +1835,17 @@ int ptwr_do_page_fault(unsigned long addr) /* Get the L2 index at which this L1 p.t. is always mapped. */ l2_idx = page->u.inuse.type_info & PGT_va_mask; if ( unlikely(l2_idx >= PGT_va_unknown) ) + { domain_crash(); /* Urk! This L1 is mapped in multiple L2 slots! */ + return 0; + } l2_idx >>= PGT_va_shift; if ( l2_idx == (addr >> L2_PAGETABLE_SHIFT) ) { MEM_LOG("PTWR failure! Pagetable maps itself at %08lx\n", addr); domain_crash(); + return 0; } /* @@ -1908,6 +1913,7 @@ int ptwr_do_page_fault(unsigned long addr) unmap_domain_mem(ptwr_info[cpu].ptinfo[which].pl1e); ptwr_info[cpu].ptinfo[which].l1va = 0; domain_crash(); + return 0; } return EXCRET_fault_fixed; @@ -1938,40 +1944,6 @@ __initcall(ptwr_init); #ifndef NDEBUG -void ptwr_status(void) -{ - unsigned long pte, *ptep, pfn; - struct pfn_info *page; - int cpu = smp_processor_id(); - - ptep = (unsigned long *)&linear_pg_table - [ptwr_info[cpu].ptinfo[PTWR_PT_INACTIVE].l1va>>PAGE_SHIFT]; - - if ( __get_user(pte, ptep) ) { - MEM_LOG("ptwr: Could not read pte at %p\n", ptep); - domain_crash(); - } - - pfn = pte >> PAGE_SHIFT; - page = &frame_table[pfn]; - printk("need to alloc l1 page %p\n", page); - /* make pt page writable */ - printk("need to make read-only l1-page at %p is %08lx\n", - ptep, pte); - - if ( ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va == 0 ) - return; - - if ( __get_user(pte, (unsigned long *) - ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va) ) { - MEM_LOG("ptwr: Could not read pte at %p\n", (unsigned long *) - ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va); - domain_crash(); - } - pfn = pte >> PAGE_SHIFT; - page = &frame_table[pfn]; -} - void audit_domain(struct domain *d) { int ttot=0, ctot=0, io_mappings=0, lowmem_mappings=0; diff --git a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c index 01d67d43ad..465563fb8f 100644 --- a/xen/arch/x86/shadow.c +++ b/xen/arch/x86/shadow.c @@ -580,15 +580,13 @@ int shadow_fault(unsigned long va, long error_code) &linear_pg_table[va >> PAGE_SHIFT])) ) { SH_VVLOG("shadow_fault - EXIT: read gpte faulted" ); - shadow_unlock(m); - return 0; + goto fail; } if ( unlikely(!(gpte & _PAGE_PRESENT)) ) { SH_VVLOG("shadow_fault - EXIT: gpte not present (%lx)",gpte ); - shadow_unlock(m); - return 0; + goto fail; } /* Write fault? */ @@ -598,8 +596,7 @@ int shadow_fault(unsigned long va, long error_code) { /* Write fault on a read-only mapping. */ SH_VVLOG("shadow_fault - EXIT: wr fault on RO page (%lx)", gpte); - shadow_unlock(m); - return 0; + goto fail; } l1pte_write_fault(m, &gpte, &spte); @@ -616,7 +613,10 @@ int shadow_fault(unsigned long va, long error_code) /* XXX Watch out for read-only L2 entries! (not used in Linux). */ if ( unlikely(__put_user(gpte, (unsigned long *) &linear_pg_table[va >> PAGE_SHIFT])) ) + { domain_crash(); + goto fail; + } /* * Update of shadow PTE can fail because the L1 p.t. is not shadowed, @@ -637,6 +637,10 @@ int shadow_fault(unsigned long va, long error_code) check_pagetable(m, current->mm.pagetable, "post-sf"); return EXCRET_fault_fixed; + + fail: + shadow_unlock(m); + return 0; } diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 8e965c5f60..df68d420fc 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -654,8 +654,6 @@ asmlinkage int do_debug(struct xen_regs *regs) struct domain *d = current; struct trap_bounce *tb = &d->thread.trap_bounce; - DEBUGGER_trap_entry(TRAP_debug, regs); - __asm__ __volatile__("movl %%db6,%0" : "=r" (condition)); /* Mask out spurious debug traps due to lazy DR7 setting */ @@ -666,6 +664,8 @@ asmlinkage int do_debug(struct xen_regs *regs) goto out; } + DEBUGGER_trap_entry(TRAP_debug, regs); + if ( !GUEST_FAULT(regs) ) { /* Clear TF just for absolute sanity. */ diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index aaf6caccef..b155938310 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -112,7 +112,7 @@ DBLFLT1:GET_CURRENT(%ebx) jmp test_all_events DBLFIX1:GET_CURRENT(%ebx) testb $TF_failsafe_return,DOMAIN_thread_flags(%ebx) - jnz domain_crash # cannot reenter failsafe code + jnz domain_crash_synchronous # cannot reenter failsafe code orb $TF_failsafe_return,DOMAIN_thread_flags(%ebx) jmp test_all_events # will return via failsafe code .previous @@ -330,7 +330,7 @@ DBLFLT2:jmp process_guest_exception_and_events .long FLT23,FIX7 , FLT24,FIX7 , FLT25,FIX7 , FLT26,FIX7 , FLT27,FIX7 .previous .section __ex_table,"a" - .long DBLFLT2,domain_crash + .long DBLFLT2,domain_crash_synchronous .previous ALIGN @@ -620,9 +620,9 @@ VFLT3: movl %gs:(%esi),%eax jmp test_all_events .section __ex_table,"a" - .long VFLT1,domain_crash - .long VFLT2,domain_crash - .long VFLT3,domain_crash + .long VFLT1,domain_crash_synchronous + .long VFLT2,domain_crash_synchronous + .long VFLT3,domain_crash_synchronous .previous .data diff --git a/xen/common/domain.c b/xen/common/domain.c index 30b0677fbb..90e893899a 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -146,8 +147,15 @@ void domain_crash(void) send_guest_virq(dom0, VIRQ_DOM_EXC); - __enter_scheduler(); - BUG(); + raise_softirq(SCHEDULE_SOFTIRQ); +} + + +void domain_crash_synchronous(void) +{ + domain_crash(); + for ( ; ; ) + do_softirq(); } void domain_shutdown(u8 reason) @@ -169,18 +177,14 @@ void domain_shutdown(u8 reason) } } - if ( reason == SHUTDOWN_crash ) - { - domain_crash(); - BUG(); - } - - current->shutdown_code = reason; - set_bit(DF_SHUTDOWN, ¤t->flags); + if ( (current->shutdown_code = reason) == SHUTDOWN_crash ) + set_bit(DF_CRASHED, ¤t->flags); + else + set_bit(DF_SHUTDOWN, ¤t->flags); send_guest_virq(dom0, VIRQ_DOM_EXC); - __enter_scheduler(); + raise_softirq(SCHEDULE_SOFTIRQ); } unsigned int alloc_new_dom_mem(struct domain *d, unsigned int kbytes) diff --git a/xen/common/schedule.c b/xen/common/schedule.c index d16c2192f4..9756b18512 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -79,7 +79,8 @@ static struct scheduler *schedulers[] = { NULL }; -/* Operations for the current scheduler. */ +static void __enter_scheduler(void); + static struct scheduler ops; #define SCHED_OP(fn, ...) \ @@ -310,7 +311,7 @@ long sched_adjdom(struct sched_adjdom_cmd *cmd) * - deschedule the current domain (scheduler independent). * - pick a new domain (scheduler dependent). */ -void __enter_scheduler(void) +static void __enter_scheduler(void) { struct domain *prev = current, *next = NULL; int cpu = prev->processor; diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 254169cd9f..8f5345375b 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -184,9 +184,20 @@ struct domain *find_domain_by_id(domid_t dom); struct domain *find_last_domain(void); extern void domain_destruct(struct domain *d); extern void domain_kill(struct domain *d); -extern void domain_crash(void); extern void domain_shutdown(u8 reason); +/* + * Mark current domain as crashed. This function returns: the domain is not + * synchronously descheduled from any processor. + */ +extern void domain_crash(void); + +/* + * Mark current domain as crashed and synchronously deschedule from the local + * processor. This function never returns. + */ +extern void domain_crash_synchronous(void) __attribute__((noreturn)); + void new_thread(struct domain *d, unsigned long start_pc, unsigned long start_stack, @@ -207,8 +218,6 @@ void init_idle_task(void); void domain_wake(struct domain *d); void domain_sleep(struct domain *d); -void __enter_scheduler(void); - extern void switch_to(struct domain *prev, struct domain *next); -- 2.30.2